﻿using System.Collections.Generic;
using System.Net.Sockets;

namespace Server.Net
{
    /// <summary>
    /// 存储数据包的缓冲池
    /// </summary>
    class BufferManager
    {
        /// <summary>
        /// 缓冲池的总大小
        /// </summary>
        private int m_numBytes;                    

        /// <summary>
        /// 存储数据包的字节数组
        /// </summary>
        private byte[] m_buffer;                

        /// <summary>
        /// 缓冲池的可用栈
        /// </summary>
        private Stack<int> m_freeIndexPool;     

        /// <summary>
        /// 可用缓冲区的索引
        /// </summary>
        private int m_currentIndex;

        /// <summary>
        /// 单个缓冲区的大小
        /// </summary>
        private int m_bufferSize;

        /// <summary>
        /// 初始化缓冲池
        /// </summary>
        /// <param name="totalBytes">缓冲区的数量</param>
        /// <param name="bufferSize">单个缓冲区大小</param>
        public BufferManager(int bufferNum, int bufferSize)
        {
            m_numBytes = bufferNum * bufferSize;
            m_currentIndex = 0;
            m_bufferSize = bufferSize;
            m_freeIndexPool = new Stack<int>();
            m_buffer = new byte[m_numBytes];
        }

        /// <summary>
        /// 分配缓冲区给SocketAsyncEventArgs实例
        /// </summary>
        /// <param name="args">SocketAsyncEventArgs实例</param>
        /// <returns>分配成功则返回true，分配失败则返回false</returns>
        public bool SetBuffer(SocketAsyncEventArgs args)
        {

            if (m_freeIndexPool.Count > 0)
            {
                args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize);
            }
            else
            {
                if ((m_numBytes - m_bufferSize) < m_currentIndex)
                {
                    return false;
                }
                args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize);
                m_currentIndex += m_bufferSize;
            }
            return true;
        }

        /// <summary>
        /// 释放SocketAsyncEventArgs实例占用的缓冲区，放回到池里，供下一次使用
        /// </summary>
        /// <param name="args">SocketAsyncEventArgs实例</param>
        public void FreeBuffer(SocketAsyncEventArgs args)
        {
            m_freeIndexPool.Push(args.Offset);
            args.SetBuffer(null, 0, 0);
        }

    }

}
